﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Xml;
using Log4Nez.Interfaces;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Reflection;
using Log4Nez.Exceptions;
using System.IO;

namespace Log4Nez.Loggers
{
    internal class CsvFileLogger : ILogger
    {
        private Dictionary<string, string> _properties = null;
        private System.IO.FileStream file = null;
        private string _filenameFormat = string.Empty;
        private string _fileLocation = string.Empty;

        public CsvFileLogger(Dictionary<string, string> properties, string filenameFormat, string fileLocation)
        {
            this._properties = properties;
            this._fileLocation = fileLocation;
            this._filenameFormat = filenameFormat;
        }

        public bool Write(TraceLevel level, object message, params string[] formatParams)
        {
            try
            {
                initFile(formatParams);
                lock (file)
                {
                    StringBuilder intestazioniStringBuilder = new StringBuilder();
                    StringBuilder rigaStringBuilder = new StringBuilder();
                    Type messageType = message.GetType();
                    List<PropertyInfo> realProperties = messageType.GetProperties().ToList<PropertyInfo>();
                    foreach (string key in _properties.Keys)
                    {
                        PropertyInfo property = realProperties.FirstOrDefault(p => p.Name == key);
                        intestazioniStringBuilder.AppendFormat("{0},",key);
                        object propertyValue = property.GetValue(message, null);
                        if (propertyValue != null)
                            rigaStringBuilder.Append(propertyValue.ToString());
                        rigaStringBuilder.Append(",");
                    }
                    rigaStringBuilder.Append("\r\n");
                    StreamWriter w = new StreamWriter(file);

                    if (file.CanWrite)
                    {
                        if (file.Position == 0)
                            w.WriteLine(intestazioniStringBuilder.ToString());
                        w.Write(rigaStringBuilder.ToString());
                    }
                    else
                        throw new IOException("I can't write the file");
                    w.Flush();
                    file.Close();
                    return false;
                }

            }
            catch (IOException ioEx)
            {
                throw new FactoryException(ioEx.Message);
            }
            catch (Exception ex)
            {
                throw new BugException(ex.Message, Enumerations.LoggerType.CvsLogger, message);
            }
        }

        private void initFile(params string[] formatParams)
        {
            string filename = string.Format(_filenameFormat, formatParams);
            filename = _fileLocation.EndsWith("\\") || _fileLocation.EndsWith("/") ? _fileLocation + filename : _fileLocation + @"\" + filename;

            if (!File.Exists(filename))
                file = File.Create(filename);
            else
                file = File.Open(filename, FileMode.Append, FileAccess.Write);
            //file = new System.IO.FileStream(filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);

        }


        public TraceLevel LoggerLevel
        {
            get;
            set;
        }
    }
}
